package hubol;

import java.util.HashSet;

import owg.util.Calc;
import owg.util.EntityBase;
import owg.util.opengl.ColorF;
import owg.util.opengl.ColorF.ColorFMutable;


public abstract class Entity extends EntityBase {
	public double x, y, xstart, ystart, xprevious, yprevious, hspeed, vspeed;
	public float xscale, yscale, angle, imageSpeed, imageSingle;
	
	public Sprite sprite = null;
	public Mask mask = null;
	public HashSet<Integer> tags = new HashSet<Integer>();
	
	public ColorFMutable color = new ColorFMutable(ColorF.WHITE);
	
	//alarma shit
	public final boolean alarmActive;
	public int[] alarm;
	
	public Entity(double x, double y){
		this(x, y, 0);
	}
	
	public Entity(double x, double y, int alarms){
		super(HMinigame.me.list, 0);
		
		//prepare alarms (if necessary)
		if (alarms == 0)
			alarmActive = false;
		else{
			alarmActive = true;
			alarm = new int[alarms];
			for (int j=0; j<alarms; j++)
				alarm[j] = -1;
		}
		
		//x and y coordinates
		this.x = x;
		this.y = y;
		xstart = x;
		ystart = y;
		xprevious = x;
		yprevious = y;
		//horizontal and vertical speeds
		hspeed = 0;
		vspeed = 0;
		//collision group id
		setTag(0);
		//image index control
		imageSingle = 0;
		imageSpeed = 1;
		//transformations
		xscale = 1;
		yscale = 1;
		angle = 0;
	}
	
	/**lets add (a) Tag(s)!!!*/
	public void addTag(int... insert){
		for (int i : insert)
			tags.add(i);
	}
	
	/**lets set the Tag!!! (wipes all collision groups currently stored!)*/
	public void setTag(int... insert){
		tags.clear();
		for (int i : insert)
			tags.add(i);
	}
	
	/**lets remove (a) Tag(s)!!!*/
	public void dropTag(int... drop){
		for (int i : drop)
			tags.remove(i);
	}
	
	/**very useful function: set x and y coordinates to the supplied values*/
	public void setPos(double x, double y){
		this.x = x;
		this.y = y;
	}
	
	public void beginStep(){
		
	}
	
	/**this advances imageSingle by imageSpeed, sets x and yprevious, and adjusts coordinates based on horizontal and vertical speeds. it also calls alarmStep()*/
	public void step(){
		if (sprite != null){
			imageSingle += imageSpeed;
			while(imageSingle >= sprite.texture.length)
				imageSingle -= sprite.texture.length;
		}
		
		xprevious = x;
		yprevious = y;
		
		x += hspeed;
		y += vspeed;
		
		if (alarmActive)
			alarmStep();
	}
	
	public void endStep(){
		
	}
	
	/**this advances the entity's alarm and calls events if necessary!!! it is not necessary to call this if you are already calling the step()*/
	public void alarmStep(){
		for (int i=0; i<alarm.length; i++){
			if (alarm[i] > -1)
				alarm[i] -= 1;
			if (alarm[i] == 0)
				alarmEvent(i);
		}
	}
	
	/**this is designed to be overridden and adjusted per your needs!!!*/
	public void alarmEvent(int i){
		
	}
	
	public void render(){
		sprite.render((int)imageSingle, x, y, xscale, yscale, angle, color);
	}
	
	public double getSpeed(){
		return Calc.dist(0, 0, hspeed, vspeed);
	}
	public double getDirection(){
		return Calc.dir(0, 0, hspeed, vspeed);
	}
	public void setSpeed(double newSpeed){
		double s = getSpeed();
		if (s!=0){
			hspeed *= newSpeed/s;
			vspeed *= newSpeed/s;
		}
		else{
			hspeed = newSpeed;
			vspeed = 0;
		}
	}
	
	public void setDirection(double dir){
		double s = getSpeed();
		hspeed = Calc.dirX(s, dir);
		vspeed = Calc.dirY(s, dir);
	}
	
	public void setDirSpeed(double dir, double newSpeed){
		setSpeed(newSpeed);
		setDirection(dir);
	}

	/**are you a member of a list of collision integers???*/
	public boolean isOfTag(int... groups) {
		for(int i : groups){
			if (tags.contains(i))
				return true;
		}
		return false;
	}
	
	/**are you a member of the following collision integer*/
	public boolean isOfTag(int group) {
		return tags.contains(group);
	}


	public boolean collidesWith(Entity other, double x, double y) {
		return mask.collidesWith(this, x, y, other);
	}
		
	
}
